﻿
namespace Patterns4Net.Core.CecilExtensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Mono.Cecil;

    /// <summary>
    /// Provides extension method for type <see cref="ICustomAttributeProvider"/>.
    /// </summary>
    public static class MemberExtensions
    {
        /// <summary>
        /// Returns <c>true</c> if member <paramref name="target"/> has an attribute of type <typeparamref name="TAttribute"/>.
        /// </summary>
        /// <param name="inherit">
        /// If <c>true</c>, than the method searches also for sub-classes of <typeparamref name="TAttribute"/>.
        /// </param>
        public static bool HasAttribute<TAttribute>(this ICustomAttributeProvider target, bool inherit = false)
        {
            return target.GetAttributes<TAttribute>(inherit).Any();
        }

        /// <summary>
        /// Returns <c>true</c> if member <paramref name="target"/> 
        /// has any attribute for which <paramref name="predicate"/> evaluates to <c>true</c>.
        /// </summary>
        public static bool HasAttribute(this ICustomAttributeProvider target, Func<CustomAttribute, bool> predicate)
        {
            return target.CustomAttributes.Any(predicate);            
        }

        /// <summary>
        /// Returns all attributes of <typeparamref name="TAttribute"/> of type <typeparamref name="TAttribute"/>.
        /// </summary>
        /// <param name="inherit">
        /// If <c>true</c>, than the method searches also for sub-classes of <typeparamref name="TAttribute"/>.
        /// </param>
        public static IEnumerable<CustomAttribute> GetAttributes<TAttribute>(this ICustomAttributeProvider target, bool inherit = false)
        {
            if (inherit == false)
            {
                return target.GetAttributes(attr => attr.AttributeType.IsEqual(typeof(TAttribute)));
            }

            return target.GetAttributes(attr => attr.AttributeType.SafeImplements(typeof(TAttribute)));            
        }

        /// <summary>
        /// Returns those attributes of <paramref name="target"/> that satisfy <paramref name="predicate"/>.
        /// </summary>
        public static IEnumerable<CustomAttribute> GetAttributes(
            this ICustomAttributeProvider target, 
            Func<CustomAttribute, bool> predicate)
        {
            return target.CustomAttributes.Where(predicate);
        }
    }
}
